﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
// add
using System.IO.Ports;
using FormBaseLib;

enum enumComPort { COM1 = 1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, COM10, COM11, COM12, COM13, COM14, COM15, COM16, COM17, COM18 }
enum enumBaudRate { B9600 = 9600, B19200 = 19200, B38400 = 38400, B57600 = 57600 }
enum enumProductGroup { SG100, EA15 }
enum enumCmdType { BarcodeScan, GetVersion, SendCommand }
enum enumDataBits { DataBit7 = 7, DataBit8 = 8 }
namespace FormBase
{
    public partial class FPGM0030 : Form
    {
        //CProject mProject = Program.gProject;
        string msScanned = string.Empty;
        string msBarcode = string.Empty;
        bool mbBarcodeShowing = false;

        enumCmdType mCmd = enumCmdType.BarcodeScan;

        SerialPort mSP = new SerialPort();
        Boolean mbAcknowledge = false;
        //CAction mAction = new CAction("FPGM0030");
        CAction mAction = new CAction();

        enumProductGroup mProductGroup = enumProductGroup.SG100;
        enumComPort mComPort = enumComPort.COM1;
        enumBaudRate mBaudRate = enumBaudRate.B9600;
        Parity mParity = Parity.None;
        enumDataBits mDataBits = enumDataBits.DataBit8;
        StopBits mStopBits = StopBits.One;
        byte[] mbaReceive;
        string msVersion;
        delegate void ShowMsgEventHandler(string sMsg, Color color1);


        int miActionStep;

        public FPGM0030()
        {
            InitializeComponent();
        }
        private void FPGM0030_Load(object sender, EventArgs e)
        {
            Text = "Barcode scanned by RS232";
            KeyPreview = true;

            CProject.gCboAddItem(cboProductGroup, typeof(enumProductGroup), true);
            CProject.gCboAddItem(cboPort, typeof(enumComPort), true);
            CProject.gCboAddItem(cboBaudRate, typeof(enumBaudRate), false);
            CProject.gCboAddItem(cboParity, typeof(Parity), true);
            CProject.gCboAddItem(cboStopBits, typeof(StopBits), true);
            CProject.gCboAddItem(cboDataBits, typeof(enumDataBits), false);

            mSP.DataReceived += new SerialDataReceivedEventHandler(mSP_DataReceived);
            mSP.ErrorReceived += new SerialErrorReceivedEventHandler(mSP_ErrorReceived);
            mSP.PinChanged += new SerialPinChangedEventHandler(mSP_PinChanged);

            myClear();
        }

        void mSP_PinChanged(object sender, SerialPinChangedEventArgs e)
        {
            string sMsg = "Pin changed.";
            ShowMsg(sMsg);
        }

        void mSP_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
        {
            SerialPort sp = (SerialPort)sender;
            //            System.Threading.Thread.Sleep(500);
            string sMsg = e.EventType.ToString();
            ShowMsg(sMsg);
        }

        void mSP_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            string sReceived;
            CProject.mApp.mAction.AppendMsgDebug("mSP_DataReceived()");
            System.Threading.Thread.Sleep(1000);
            SerialPort sp = (SerialPort)sender;
            Byte[] baReceived = new byte[sp.BytesToRead];
            int iLenReceived = sp.Read(baReceived, 0, sp.BytesToRead);
            switch (mCmd)
            {
                case enumCmdType.GetVersion:
                    switch (miActionStep)
                    {
                        case 0:
                            if (baReceived[0] != 21)
                            {
                                mAction.EndError("Acknowledge!");
                                break;
                            }
                            byte[] baSend = new byte[4] { 2, 133, 3, 132 };
                            sp.Write(baSend, 0, baSend.Length);
                            miActionStep = 1;
                            break;
                        case 1:
                            if (baReceived[0] != 6)
                            {
                                mAction.EndError("First Byte <> 6 after Acknowledge.");
                                break;
                            }
                            //sReceived = System.Text.Encoding.UTF8.GetString(baReceived);

                            byte[] baVersion = new byte[iLenReceived - 6];
                            Array.Copy(baReceived, 4, baVersion, 0, baVersion.Length);
                            string sVersion = System.Text.Encoding.UTF8.GetString(baVersion);

                            // wrong thread
                            //txtMsg.Text = sReceived; 
                            mAction.EndSuccess("SUCCESS");
                            ShowMsg("Version=" + sVersion);
                            break;
                        default:
                            mAction.EndError("Wrong step!");
                            break;
                    }
                    break;
                case enumCmdType.SendCommand:
                    switch (miActionStep)
                    {
                        case 0:
                            if (baReceived[0] == 6)
                            {
                                CProject.mApp.PopupMsg("check sum=06, ok!");
                                //mAction.miStep = 1;
                                break;
                            }
                            if (baReceived[0] == 21)
                            {
                                CProject.mApp.PopupMsg("check sum error, response =21");
                                break;
                            }
                            CProject.mApp.PopupMsg("todo, response unknown!");
                            break;
                        case 1:
                            if (baReceived[0] != 6)
                            {
                                mAction.EndError("First Byte <> 6 after Acknowledge.");
                                break;
                            }
                            //sReceived = System.Text.Encoding.UTF8.GetString(baReceived);

                            byte[] baVersion = new byte[iLenReceived - 6];
                            Array.Copy(baReceived, 4, baVersion, 0, baVersion.Length);
                            string sVersion = System.Text.Encoding.UTF8.GetString(baVersion);

                            // wrong thread
                            //txtMsg.Text = sReceived; 
                            mAction.EndSuccess("SUCCESS");
                            ShowMsg("Version=" + sVersion);
                            break;
                        default:
                            mAction.EndError("Wrong step!");
                            break;
                    }
                    break;
                default:
                    msScanned = System.Text.Encoding.UTF8.GetString(baReceived);
                    ShowMsg("Barcode=" + msScanned);
                    break;
            }
        }

        private void myClear()
        {
            txtBarcode.Clear();
            txtMsg.Clear();
            txtHex.Clear();
            txtLength.Clear();
            ActiveControl = txtBarcode;
        }
        private void myClose()
        {
            Close();
        }



        private void myShowFound()
        {
            mbBarcodeShowing = true;
            myClear();
            txtBarcode.Text = msBarcode;
            txtLength.Text = msScanned.Length.ToString();
            txtHex.Text = CProject.gStringASCToHex(msScanned);
            txtMsg.Text = "Success.";
        }
        private void myShowNotFound()
        {
            mbBarcodeShowing = true;
            myClear();
            txtBarcode.Text = msBarcode;
            txtLength.Text = msScanned.Length.ToString();
            txtHex.Text = CProject.gStringASCToHex(msScanned);
            txtMsg.Text = "Success scanned but not found in DB.";
        }
        private void textBox1_TextChanged(object sender, EventArgs e)
        {

        }
        private string myGetBarcode(string sInput)
        {
            string s1;

            s1 = CProject.gCRLFRemove(sInput);
            return s1;

        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            myClear();

        }


        private void FPGM0030_KeyPress(object sender, KeyPressEventArgs e)
        {
            string s1 = string.Empty;
            char cInputKeyPress = e.KeyChar;
            switch (cInputKeyPress)
            {
                case (char)Keys.Escape:
                    DialogResult d1 = MessageBox.Show("Close ?" + s1, "Confirm", MessageBoxButtons.OKCancel);
                    if (d1 == DialogResult.OK)
                    {
                        //CProject.End();
                        this.Close();
                    }
                    break;
                case (char)Keys.LineFeed:
                    CProject.mApp.mAction.AppendMsgDebug("FPGM0020.KeyPress().Enter");
                    msScanned = msScanned + ((char)Keys.LineFeed);
                    CProject.mApp.mAction.AppendMsgDebug("msBarcodeScanned=" + msScanned);
                    Boolean bFound = false;
                    //txtHex.Text = mProject.StringASCToHex(msScanned);
                    msBarcode = myGetBarcode(msScanned);
                    if (msBarcode.Length < 1)
                    {
                        e.Handled = true;
                        return;
                    }
                    //txtBarcode.Text = msBarcode;
                    switch (msBarcode)
                    {
                        case "T": // Test
                            bFound = true;
                            msBarcode = "Test";
                            break;
                        case "V": // Version
                            bFound = true;
                            msBarcode = CProject.mApp.msAssemblyVersion;
                            break;
                        case "7192751043689":
                            bFound = true;
                            break;
                        case "ABCDEFGH":
                            bFound = true;
                            break;
                    }
                    if (bFound)
                        myShowFound();
                    else
                        myShowNotFound();

                    msScanned = string.Empty;
                    //e.Handled = true;
                    break;

                case (char)Keys.F1:
                    // KeyPrress抓不到F1, 改用輸入VERSION字串處理.
                    //MessageBox.Show(String.Format("Version {0}", Assembly.GetExecutingAssembly().GetName().Version.ToString()), "Information");
                    CProject.mApp.PopupMsg(CProject.mApp.msAssemblyVersion);
                    //e.Handled = true;
                    break;
                default:
                    msScanned += cInputKeyPress;
                    //e.Handled = true;
                    break;
            }
            e.Handled = true;

        }

        private void FPGM0030_FormClosing(object sender, FormClosingEventArgs e)
        {
            // release any open resources.

        }

        private void btnDefaultRS232_Click(object sender, EventArgs e)
        {
            //mProject.SetComboBoxIndexByText(cboPort, Enum.GetName(typeof(enumComPort), enumComPort.COM1));
            CProject.gCboSetIndex(cboProductGroup, enumProductGroup.SG100.ToString());
            CProject.gCboSetIndex(cboPort, enumComPort.COM1.ToString());
            CProject.gCboSetIndex(cboBaudRate, ((int)enumBaudRate.B9600).ToString());
            CProject.gCboSetIndex(cboParity, Parity.None.ToString());
            CProject.gCboSetIndex(cboDataBits, ((int)enumDataBits.DataBit8).ToString());
            CProject.gCboSetIndex(cboStopBits, StopBits.One.ToString());
        }


        private void btnConnect_Click(object sender, EventArgs e)
        {
            myConnect();
        }

        private void myConnect()
        {
            object o1;
            int i1;
            bool b1;

            lblConnected.Text = string.Empty;
            if (mSP.IsOpen)
            {
                ShowMsgError("Serial port is opening.");
                return;
            }

            if (CProject.gGetEnumItem(typeof(enumProductGroup), cboProductGroup.Text, out o1))
                mProductGroup = (enumProductGroup)o1;
            else
            {
                ShowMsgError("Wrong product group=" + cboProductGroup.Text);
                return;
            }

            if (CProject.gGetEnumItem(typeof(enumComPort), cboPort.Text, out o1))
                mComPort = (enumComPort)o1;
            else
            {
                ShowMsgError("Wrong COM PORT=" + cboPort.Text);
                return;
            }

            b1 = false;
            if (int.TryParse(cboBaudRate.Text, out i1))
                if (CProject.gGetEnumItem(typeof(enumBaudRate), i1, out o1))
                {
                    mBaudRate = (enumBaudRate)o1;
                    b1 = true;
                }
            if (!b1)
            {
                ShowMsgError("Wrong BAUD RATE=" + cboBaudRate.Text);
                return;
            }

            if (CProject.gGetEnumItem(typeof(Parity), cboParity.Text, out o1))
                mParity = (Parity)o1;
            else
            {
                ShowMsgError("Wrong PARITY=" + cboParity.Text);
                return;
            }


            b1 = false;
            if (int.TryParse(cboDataBits.Text, out i1))
                if (CProject.gGetEnumItem(typeof(enumDataBits), i1, out o1))
                {
                    mDataBits = (enumDataBits)o1;
                    b1 = true;
                }
            if (!b1)
            {
                ShowMsgError("Wrong BAUD RATE=" + cboDataBits.Text);
                return;
            }


            if (CProject.gGetEnumItem(typeof(StopBits), cboStopBits.Text, out o1))
                mStopBits = (StopBits)o1;
            else
            {
                ShowMsgError("Wrong Stop Bits=" + cboStopBits.Text);
                return;
            }


            mSP.PortName = mComPort.ToString();
            mSP.BaudRate = (int)mBaudRate;
            mSP.Parity = mParity;
            mSP.StopBits = mStopBits;
            mSP.DataBits = (int)mDataBits;

            mSP.Handshake = Handshake.None;
            mSP.ReadTimeout = 2000;
            mSP.WriteTimeout = 500;
            mSP.DtrEnable = true;
            mSP.RtsEnable = true;
            try
            {
                mSP.Open();
                lblConnected.Text = "Connected";
                ShowMsg(string.Empty);
            }
            catch (Exception ex)
            {
                ShowMsgError(ex.Message);
            }
        }
        private void OnShowMsg(string sMsg, Color color1)
        {
            lblStatus.Text = sMsg;
            if (lblStatus.ForeColor != color1)
                lblStatus.ForeColor = color1;
        }


        private void myGetVersion()
        {
            byte[] baSend;
            mAction.BeginAction("myGetVersion()");
            if (!mSP.IsOpen)
            {
                ShowMsgError("Please connect first.");
                return;
            }

            mCmd = enumCmdType.GetVersion;
            mbAcknowledge = false;

            switch (mProductGroup)
            {
                case enumProductGroup.EA15:
                    int iChecksum;
                    int iCmdLength = 10;
                    baSend = new byte[14] { 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                    //baSend = new byte[14] { 0, 21 , 0, 128, 0, 0, 76, 128, 0, 0, 0, 0, 0, 0 };
                    iChecksum = 0;
                    for (int i = 0; i < iCmdLength; i++)
                        iChecksum = iChecksum + (baSend[i] * (iCmdLength - i));

                    if (iChecksum != 1773)
                    {
                        ShowMsgError("Checksum = " + iChecksum.ToString());
                        return;
                    }
                    ShowMsg("Checksum ok!");
                    myChecksumn(baSend);
                    return;


                    mSP.Write(baSend, 0, baSend.Length);
                    break;
                case enumProductGroup.SG100:
                    baSend = new byte[4] { 2, 131, 3, 131 };
                    mSP.Write(baSend, 0, baSend.Length);
                    break;
                default:
                    ShowMsgError("Wrong Product group !");
                    break;
            }
        }

        public void ShowMsg(string sMsg)
        {
            Invoke(new ShowMsgEventHandler(OnShowMsg), new object[] { sMsg, SystemColors.ControlText });
        }
        public void ShowMsgError(string sMsg)
        {
            Invoke(new ShowMsgEventHandler(OnShowMsg), new object[] { sMsg, Color.Red });
        }
        private void myChecksumn(byte[] baInput)
        {
            int iChecksum;
            int iCmdLength = 10;
            if (baInput.Length < 14)
            {
                ShowMsgError("Length must be 14");
                return;
            }
            iChecksum = 0;
            for (int i = 0; i < iCmdLength; i++)
                iChecksum = iChecksum + (baInput[i] * (iCmdLength - i));

            if (iChecksum != 1773)
            {
                ShowMsgError("Checksum = " + iChecksum.ToString());
                return;
            }
            CBit.CopyToByteArray(iChecksum, baInput, 10);
            ShowMsg("Checksum ok!");
        }

        private void btnDisconnect_Click(object sender, EventArgs e)
        {
            myDisconnect();
        }
        private void myDisconnect()
        {
            mSP.Close();
            lblConnected.Text = string.Empty;
            ShowMsg("Disconnect");
        }

        private void btnGetVersion_Click(object sender, EventArgs e)
        {
            myGetVersion();
        }

        private void btnSampleCommand_Click(object sender, EventArgs e)
        {
            mySendCommand();
        }
        private void mySendCommand()
        {
            byte[] baSend;
            mAction.BeginAction("mySendCommand");
            if (!mSP.IsOpen)
            {
                ShowMsgError("Please connect first.");
                return;
            }

            mCmd = enumCmdType.SendCommand;
            mbAcknowledge = false;

            switch (mProductGroup)
            {
                case enumProductGroup.EA15:
                    int iChecksum;
                    int iCmdLength = 10;
                    baSend = new byte[14] { 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                    //baSend = new byte[14] { 0, 21 , 0, 128, 0, 0, 76, 128, 0, 0, 0, 0, 0, 0 };
                    iChecksum = 0;
                    for (int i = 0; i < iCmdLength; i++)
                        iChecksum = iChecksum + (baSend[i] * (iCmdLength - i));

                    if (iChecksum != 1773)
                    {
                        ShowMsgError("Checksum = " + iChecksum.ToString());
                        return;
                    }
                    ShowMsg("Checksum ok!");
                    myChecksumn(baSend);
                    return;


                    mSP.Write(baSend, 0, baSend.Length);
                    break;
                case enumProductGroup.SG100:
                    baSend = new byte[4] { 2, 130, 3, 131 };
                    if (!myChecksumXOR(baSend, 3))
                        ShowMsgError("XOR checksum fail !");

                    mSP.Write(baSend, 0, baSend.Length);
                    break;
                default:
                    ShowMsgError("Wrong Product group !");
                    break;
            }
        }

        private bool myChecksumXOR(byte[] ba1, int iIndexXORByte)
        {
            byte bSum;

            bSum = ba1[0];
            for (int i = 1; i < ba1.Length; i++)
                if (i != iIndexXORByte)
                    bSum = CProject.gXOR(bSum, ba1[i]);

            if (bSum == ba1[iIndexXORByte])
                return true;
            else
                return false;
        }

    }
}
